package model;

import control.ControllerPlayer;
import java.util.HashSet;
import java.util.Set;
import vinciappli.ProvinceSubType;


public class Empire {

    private Set<Province> listProvinces;
    private boolean depressed;
    private Civilization civilization;

    public Empire(Civilization civilization) {
        this.depressed = false;
        this.civilization = civilization;
    }

    /**
     * Check if an empire is nearby to another one
     * @param e : Another empire
     * @return : Provinces from the current empire which are nearby the other empire (e)
     */
    public Set<Province> isAdjacent (Empire e) {
        Set<Province> adjProvinces = new HashSet<Province>();
        
        for(Province p : listProvinces)
        {
            adjProvinces.addAll(p.getNearbyProvinces());
        }

        // TODO : Check si tous les cas sont pris en compte pour identifier l'adjacence des 2 empires
        if(adjProvinces.retainAll(e.listProvinces) || adjProvinces.containsAll(e.listProvinces))
        {
            return adjProvinces;
        }
        else
        {
            return null;
        }
    }

    /**
     * Check if the empire gets all its provinces closed each one from the others or not
     * @return : null if the empire is unified, otherwise Set of the provinces, which has to be owned, to get the empire unified
     */
    public Set<Province> isUnified () {
        Set<Province> adjProvinces = new HashSet<Province>();

        for(Province p : listProvinces)
        {
            adjProvinces.addAll(p.getNearbyProvinces());
            adjProvinces.retainAll(listProvinces);
            for(SeaArea sa : p.getNearbySeaAreas())
            {
                adjProvinces.addAll(sa.getNearbyProvinces());
                adjProvinces.retainAll(listProvinces);
            }
        }
        if(adjProvinces.size() == listProvinces.size())
        {
            return null;
        }
        else
        {
            Set<Province> unlinkProvinces = new HashSet<Province>();
            unlinkProvinces.addAll(listProvinces);
            unlinkProvinces.removeAll(adjProvinces);
            return unlinkProvinces;
        }
    }

    /**
     * Remove all the troops from the empire except one (all the provinces are still owned)
     */
    public void mobilizeMaximumTroops()
    {
        int nbTroops = 0;
        Player p = ControllerPlayer.getPlayerFromEmpire(this);
        for(Province pr : listProvinces)
        {
            nbTroops += pr.getTerritoryOccupation().get(p.getNickname()) - 1;
            pr.getTerritoryOccupation().put(p.getNickname(), 1);
        }
        p.setAvailableTroopsFromCurrentNumber(nbTroops);
    }

    /**
     * Count all provinces from an empire of a selected type (moutain, forest)
     * @param type : Selected type
     * @return : Amount of provinces
     */
    public int getNbProvinceByType(String type)
    {
        int pts = 0;
        for(Province p : listProvinces)
        {
            if(p.getFieldType().equals(type))
            {
                pts++;
            }
        }
        return pts;
    }

    /**
     * Count all provinces from an empire of a selected subtype (coastal, farming, ...)
     * @param ps : Selected type
     * @return : Amount of provinces
     */
    public int getNbProvinceBySubType(ProvinceSubType ps)
    {
        int pts = 0;
        for(Province p : listProvinces)
        {
            if(p.getSubtypes().contains(ps))
            {
                pts++;
            }
        }
        return pts;
    }
    

    /***************************** GETTERS & SETTERS **************************/

    public boolean isDepressed () {
        return depressed;
    }

    public void setDepressed (boolean val) {
        this.depressed = val;
    }

    public Set<Province> getListProvinces () {
        return listProvinces;
    }

    public void setListProvinces (Set<Province> val) {
        this.listProvinces = val;
    }

    public Civilization getCivilization () {
        return civilization;
    }

    public void setCivilization (Civilization val) {
        this.civilization = val;
    }

}

